from Event import EventBase

from direct.showbase.DirectObject import DirectObject
from direct.task import *
from direct.distributed.PyDatagram import PyDatagram
from direct.distributed.PyDatagramIterator import PyDatagramIterator
from MainMenu import UIBuilder

from panda3d.core import *

class Network(DirectObject):
    """description of class"""
    Connected = False

    tcpSocket = None

    def __init__(self):
        self.cManager = QueuedConnectionManager()
        self.cListener = QueuedConnectionListener(self.cManager, 0)
        self.cReader = QueuedConnectionReader(self.cManager, 0)
        self.cWriter = ConnectionWriter(self.cManager,0)

        
        self.DataRecived = EventBase()

    def CreateDatagram(self, msg):
        dt = PyDatagram()
        dt.addString(msg)
        return dt

    def Disconnect(self):
        pass

    def ReaderPollingTask(self,taskdata):
        try:
            if self.cReader.dataAvailable():
                datagram=NetDatagram()  # catch the incoming data in this instance
                # Check the return value; if we were threaded, someone else could have
                # snagged this data before we did
                if self.cReader.getData(datagram):
                    iterator = PyDatagramIterator(datagram)

                    self.DataRecived(iterator.getString())
        except e:
            UIBuilder.ShowMessage(e, "Exception")
        return Task.cont

    def Send(self, msg):
        if self.Connected and self.tcpSocket != None:
            self.cWriter.send(self.CreateDatagram(msg), self.tcpSocket)
            

class Server(Network):
    """"""

    def __init__(self):
        Network.__init__(self) 
        self.tcpSocket = None
        self.ClientConnected = EventBase()

    def Connect(self, port):
        self.socket = self.cManager.openTCPServerRendezvous(port, 1000)
        self.cListener.addConnection(self.socket)
        taskMgr.add(self.ListenerPollingTask, "Poll the connection listener", -39)
        taskMgr.add(self.ReaderPollingTask, "Poll the connection reader", -40)
        self.Connected = True
        
    def Disconnect(self):    
        if self.Connected:
            if self.client:
                self.cReader.removeConnection(self.tcpSocket)
            self.cManager.closeConnection(self.socket)
            taskMgr.remove("Poll the connection reader")
            taskMgr.remove("Poll the connection listener")


    def ListenerPollingTask(self, taskdata):
        if self.cListener.newConnectionAvailable():
 
            rendezvous = PointerToConnection()
            netAddress = NetAddress()
            newConnection = PointerToConnection()
 
            if self.cListener.getNewConnection(rendezvous,netAddress,newConnection):
                self.tcpSocket = newConnection.p() # Remember connection
                self.cReader.addConnection(self.tcpSocket)     # Begin reading connection                
                self.ClientConnected(None)
        return Task.cont

class Client(Network):
    """"""

    def __init__(self):
        Network.__init__(self)

    def Connect(self, address, port):
        try:
            self.tcpSocket = self.cManager.openTCPClientConnection( address,port,1000)
            if self.tcpSocket:
                self.cReader.addConnection(self.tcpSocket)
                self.ConnectedToServer(None)
                self.Connected = True
            taskMgr.add(self.ReaderPollingTask, "Poll the connection reader", -40)
        except e:
            UIBuilder.ShowMessage("Cannot connect to server: {0}:{1]".format(address, port), "Exception")

    def Disconnect(self):
        if self.Connected:
            self.cReader.closeConnection(self.tcpSocket)
            self.Connected = False
            taskMgr.remove("Poll the connection reader")